/**
 * 
 */
package com.aqarat.controller;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpSession;

import com.aqarat.entity.Apartment;
import com.aqarat.entity.Building;
import com.aqarat.entity.Floor;
import com.core.transaction.EntityManagerClass;
import com.core.util.Utils;
import com.entity.RegisteredUser;

/**
 * @author karimsherif
 * 
 */
public class AqaratControllerImpl implements AqaratController, Serializable {
	private static final long serialVersionUID = 1L;
	RegisteredUser registeredUser;
	HttpSession session;
	EntityManager em = null;

	public AqaratControllerImpl() {
		em = EntityManagerClass.getEntityManagerFactory().createEntityManager();
	}

	public void saveBuilding(Building building, Floor floor,
			List<Apartment> apartmentList) throws Exception {
		try {
			em.getTransaction().begin();
			if (building.getRecid() == null) {
				em.persist(building);
			} else {
				em.merge(building);
			}
			for (int i = 1; i <= building.getNumberOfFloors(); i++) {
				Floor flooor = new Floor();
				flooor.setNumberOfApartments(floor.getNumberOfApartments());
				flooor.setNo((long) i);
				flooor.setBuildingId(building.getRecid());
				if (flooor.getRecid() == null) {
					em.persist(flooor);
				} else {
					em.persist(flooor);
				}
					Long apartmentNo = 1L;
					
					for (Apartment apartmentt : apartmentList) {
//					for (int no=0;no<=apartmentList.size();no++) {
						Apartment apartment=new Apartment();
						apartment.setFloorId(flooor.getRecid());
						apartment.setNo(apartmentNo);
						apartment.setArea(apartmentt.getArea());
						if (apartment.getRecid() == null) {
							em.persist(apartment);
						} else {
							em.persist(apartment);
						}
						apartmentNo++;
					}
			}

			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		} finally {
			if (em != null) {
				em.close();
			}
		}

	}

	public void saveApartment(Apartment apartment) throws Exception {
		try {
			em.getTransaction().begin();
			if (apartment.getRecid() == null) {
				em.persist(apartment);
			} else {
				em.merge(apartment);
			}
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		} finally {
			if (em != null) {
				em.close();
			}
		}
	}

	public List<Building> getBuildingList() throws Exception {
		return em.createQuery("select b from Building b").getResultList();
	}

	public List<Floor> getFloorListByBuildingId(Long buildingId)
			throws Exception {
		return em.createQuery("select f from Floor f where f.building.recid=:buildingId")
				.setParameter("buildingId", buildingId).getResultList();
	}

	public List<Apartment> getApartmentList(Apartment apartment)
			throws Exception {
		CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
		CriteriaQuery<Apartment> criteriaQuery = criteriaBuilder
				.createQuery(Apartment.class);
		Root<Apartment> apartmentRoot = criteriaQuery.from(Apartment.class);
		Join<Floor,Apartment>floorApartmentRoot=apartmentRoot.join("floor",JoinType.LEFT);
		Join<Building,Floor>buildigFloorRoot=floorApartmentRoot.join("building",JoinType.LEFT);
		
		criteriaQuery.select(apartmentRoot);

		Predicate criteria = null;
		Predicate criteriaTemp = null;
		if (apartment.getFloor() != null && apartment.getFloor().getNo() != null) {
			criteriaTemp = criteriaBuilder.equal(apartmentRoot.get("floor").get("no"),
					apartment.getFloor().getNo());
			criteria=(criteria==null? criteriaTemp:criteriaBuilder.and(criteria, criteriaTemp));
//			if (null == criteria) {
//				criteria = criteriaTemp;
//			} else {
//				criteria = criteriaBuilder.and(criteria, criteriaTemp);
//			}
		}
		if (apartment.getFloor() != null
				&& apartment.getFloor().getBuilding() != null) {
			criteriaTemp = criteriaBuilder.equal(
					apartmentRoot.get("floor").get("building").get("recid"), apartment
							.getFloor().getBuilding().getRecid());
			criteria=(criteria==null? criteriaTemp:criteriaBuilder.and(criteria, criteriaTemp));

		}
		if (Utils.isNotEmpty(apartment.getNo())) {
			criteriaTemp = criteriaBuilder.equal(apartmentRoot.get("no"),
					apartment.getNo());
			
			criteria=(criteria==null? criteriaTemp:criteriaBuilder.and(criteria, criteriaTemp));
		}
		
		if (null != criteria) {
			criteriaQuery.where(criteria);
		}

		Query query = em.createQuery(criteriaQuery);
		return query.getResultList();
	}

}
